import 'dart:typed_data';

import 'package:flutter/cupertino.dart';
import 'package:frontend/models/address.dart';
import 'package:frontend/models/contacts.dart';
import 'package:frontend/models/groupMessages.dart';
import 'package:frontend/models/order.dart';
import 'package:frontend/models/personalGroups.dart';
import 'package:frontend/models/personalMessages.dart';
import 'package:frontend/models/utils.dart';

import '../models/briefItems.dart';
import '../models/global.dart';
import '../models/itemInfo.dart';
import '../models/store.dart';
import '../models/user.dart';
import 'package:dio/dio.dart';

var options = BaseOptions(baseUrl: 'http://localhost:3000');
//var options = BaseOptions(baseUrl: 'http://10.0.2.2:3000'); 用于Android
var dio = Dio(options);

Future<void> requestRegister(String name, String pwd, Uint8List? img) async {
  // 注意用户可能不上传头像
  var resp = await dio.post('/user/register/', data: {
    'username': name,
    'password': pwd,
    'confirmedPassword': pwd,
    'img': img != null ? bytes2base64(img) : ''
  });
  // 返回的Json结构见User类
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<User> requestLogin(String name, String pwd) async {
  var resp =
      await dio.post('/user/login/', data: {'username': name, 'password': pwd});
  String token = (resp.data as Map<String, dynamic>)['token'];
  var map = resp.data as Map<String, dynamic>;
  int id = map['id'];
  print(token);
  dio.options.headers['Authorization'] = "Bearer $token";
  return User(name, pwd, token, base2bytes(map['img']), id);
}

Future<BriefItems> mockSearchData(String keywords) async {
  return Future.delayed(const Duration(seconds: 1), () {
    return BriefItems(<BriefItem>[
      for (final i
          in List.generate(keywords.isNotEmpty ? keywords.length : 7, (x) => x))
        BriefItem(Uint8List.fromList([0x0]), "chick", 1919, i)
    ]);
  });
}

/// mock开始的都是生成模拟数据的测试方法
Future<ItemInfo> mockItemInfo(int id) async {
  return Future.delayed(const Duration(seconds: 1), () {
    return ItemInfo(
        Uint8List.fromList([]),
        "chick",
        1919,
        810,
        "zyntm",
        "你干嘛",
        List<Comment>.generate(
            100,
            (index) =>
                Comment("Ayaya", "yarimasune", Uint8List.fromList([0x0]))),
        0);
  });
}

/// 获取物品的详细信息，用于显示物品的详细信息页面
/// 使用id查询
Future<ItemInfo> queryItemInfo(int id) async {
  var resp = await dio.get('/shop/items/', queryParameters: {'id': id});
  return ItemInfo.fromJson(resp.data as Map<String, dynamic>);
}

/// 根据关键词搜索物品，
Future<BriefItems> queryItemByKeywords(String keyword) async {
  var resp = await dio
      .post('/shop/fetchGoodByName/', queryParameters: {'good_name': keyword});

  return BriefItems.fromJson(resp.data as Map<String, dynamic>);
}

Future<BriefItems> queryAllItems() async {
  var resp = await dio.get('/shop/fetch/');
  print(resp.data);
  return BriefItems.fromJson(resp.data as Map<String, dynamic>);
}

Future<void> submitOrder(int userId, int goodId, int addressId) async {
  var resp = await dio.post('/shop/buySingle/', data: {
    'goodId': goodId,
    'buyerId': userId,
    'addressId': addressId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

/*Future<void> submitOrders(int userId, List<int> goodId) async {
  var resp = await dio.post('/shop/buyVarious/', data: {
    'goodId': goodId,
    'buyerId': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}*/

Future<void> submitComment(int goodId, int userId, String text) async {
  var resp = await dio.post('/user/comment/', data: {
    'commentator_id': userId,
    'good_id': goodId,
    'text': text,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> publishItem(
    Uint8List img, String name, int price, String description) async {
  var resp = await dio.post('/store/insert/', data: {
    'user_id': Global.profile.user!.id,
    'good_name': name,
    'good_text': description,
    'good_price': price,
    'good_img': bytes2base64(img),
    'store_id': Global.profile.store!.store_id,
    'good_type': "data"
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> delItemInStore(int itemId) async {
  var resp = await dio.post('/shop/delete/', data: {
    //'userId': Global.profile.user!.id,
    'good_id': itemId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> addToCart(int userId, int goodId) async {
  var resp = await dio.post('/cart/insert/', data: {
    'goodId': goodId,
    'userId': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> delFromCart(int userId, int goodId) async {
  var resp = await dio.post('/cart/delete/', data: {
    'goodId': goodId,
    'userId': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> clearCart(int userId) async {
  var resp = await dio.post('/cart/clear/', data: {
    'userId': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> checkOutAllInCart(int userId, int addressId) async {
  var resp = await dio.post('/cart/checkOut/', data: {
    'userId': userId,
    'addressId': addressId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<BriefItems> fetchCart(int userId) async {
  var resp = await dio.post('/cart/fetch/', data: {
    'userId': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return BriefItems.fromJson(map);
  } else {
    throw Exception();
  }
}

Future<Store?> fetchStore(int userId) async {
  var resp = await dio.post('/store/fetch/', data: {
    'user_id': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] != 'success') {
    return null;
  } else {
    return Store.fromJson(map);
  }
}

Future<void> openStore(int userId, String storeName) async {
  var resp = await dio
      .post('/store/open/', data: {'user_id': userId, 'store_name': storeName});
}

// chatting related /////////////
Future<PersonalGroups?> fetchPersonalGroups(int userId) async {
  // print('requireing chatting page');
  var resp = await dio.post('/chat/getRelation/', data: {
    'user_id': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] != 'success') {
    return null;
  } else {
    return PersonalGroups.fromJson(map);
  }
}

Future<contacts?> fetchPersonalMessages_1(int senderId) async {
  var resp = await dio.post('/chat/getMessageSingleEnd/', data: {
    'sender_id': senderId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] != 'success') {
    return null;
  } else {
    return contacts.fromJson(map);
  }
}

Future<PersonalMessages?> fetchPersonalMessages_2(
    int senderId, int receiverID) async {
  var resp = await dio.post('/chat/getMessageDoubleEnd/', data: {
    'user1_id': senderId,
    'user2_id': receiverID,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] != 'success') {
    return null;
  } else {
    return PersonalMessages.fromJson(map);
  }
}

Future<GroupMessages?> fetchGroupMessages(int groupId) async {
  var resp = await dio.post('/chat/getGroupMessage/', data: {
    'group_id': groupId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] != 'success') {
    return null;
  } else {
    return GroupMessages.fromJson(map);
  }
}

Future<void> addPersonalMessage(
    int senderId, int receiverId, String message, int time) async {
  var resp = await dio.post('/chat/addPersonalMessage/', data: {
    'sender_id': senderId,
    'receiver_id': receiverId,
    'message': message,
    'time': time,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> addGroupMessage(
    int groupId, int senderId, String message, int time) async {
  var resp = await dio.post('/chat/addGroupMessage/', data: {
    'group_id': groupId,
    'sender_id': senderId,
    'message': message,
    'time': time,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}
// end of chatting related /////////////

// begin of address related
Future<List<Address>> fetchAddresses(int userId) async {
  var resp = await dio.post('/address/fetch/', data: {
    'user_id': userId,
  });
  var map = resp.data as Map<String, dynamic>;
  List<dynamic> l = map['addresses'];
  return l.map((e) => Address.fromJson(e)).toList();
}

Future<void> addAddress(Address address) async {
  var resp = await dio.post('/address/add/', data: {
    'user_id': Global.profile.user!.id,
    'address': address.toJson(),
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> updateAddress(int addressId, Address address) async {
  var resp = await dio.post('/address/update/', data: {
    'address_id': addressId,
    'address': address.toJson(),
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}

Future<void> delAddress(int addressId) async {
  var resp = await dio.post('/address/delete/', data: {
    'address_id': addressId,
  });
  var map = resp.data as Map<String, dynamic>;
  if (map['error_message'] == 'success') {
    return;
  } else {
    throw Exception();
  }
}
//end of address related

Future<List<Order>> fetchOrders() async {
  var resp = await dio
      .post('/order/fetch/', data: {'user_id': Global.profile.user!.id});
  var map = resp.data as Map<String, dynamic>;
  List<dynamic> l = map['orders'];
  return l.map((e) => Order.fromJson(e)).toList();
}
